﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InformationRetrieval.Wildcard
{
    /// <summary>
    /// Contains helper methods for wildcard indizes
    /// </summary>
    internal static class WildcardTools
    {
        /// <summary>
        /// Determines whether the input text matches the query. Matching is 
        /// performed on-the-fly (without using any index) and case-insensitive
        /// The query may contain an arbitrary number of wildcards '*'. 
        /// </summary>
        /// <param name="text">Input text</param>
        /// <param name="query">Query text, with or without wildcards</param>
        /// <returns>True if the query matches the input text</returns>
        internal static bool MatchWildcard(string text, string query)
        {
            if (String.IsNullOrEmpty(text) || String.IsNullOrEmpty(query))
                return false;

            text = text.ToLower();
            query = query.ToLower();
            string[] tokens = query.Split(new[] { '*' }, StringSplitOptions.RemoveEmptyEntries);

            // query is "*" -> always match
            if (tokens.Length == 0)
                return true;

            // Start doesn't match
            if (query[0] != '*' && !text.StartsWith(tokens[0]))
                return false;
            // End doesn't match
            if (query[query.Length - 1] != '*' && !text.EndsWith(tokens[tokens.Length - 1]))
                return false;

            // Match all tokens
            int lastMatchPos = 0;
            for (int i = 0; i < tokens.Length && lastMatchPos < text.Length; i++)
            {
                lastMatchPos = text.IndexOf(tokens[i], lastMatchPos);
                if (lastMatchPos == -1) // token not found
                    return false;
                else lastMatchPos += tokens[i].Length;

                // no input text left, but there are still some pending tokens
                if (lastMatchPos >= text.Length && i < tokens.Length - 1)
                    return false;
            }

            return true;
        }
    }
}
